﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;

public class EnemyGenerator : MonoBehaviour, ItemTriggerReceiver
{
    public enum EnumMode
    {
        FixPostion = 0,
        RelativePostion,
        GlobalLeft,
        GlobalRight,
    }

    [System.Serializable]
    public struct Config
    {
        [Tooltip("敌人种类")]
        public GameObject enemyPrefab;

        [Tooltip("生成模式")]
        public EnumMode mode;
        [Tooltip("位置")]
        public Vector2 position;
        public LayerMask groundLayer;
    }


    [Header("基本配置")]
    [Tooltip("生成敌人的数量，如果小于0则无限生成")]
    public int genTimes = -1;

    public SeqAction genAction=new (){intervalTime=3.0f};

    [Header("生成位置")]
    public Config[] configs;

    private Camera mainCamera;




    private bool working;
    private float lastGenerationTime;
    private void Awake() {
        mainCamera=Camera.main;
        GetComponent<SpriteRenderer>().sprite = null;
    }
    private void FixedUpdate()
    {
        if (working)
        {
            genAction.Update((SeqAction seq)=>{
                if(genTimes==0){
                    return;
                }
                configs.Action((Config config)=>{
                    switch (config.mode)
                    {
                        case EnumMode.FixPostion:
                            GenEnemyAtPoint(config.enemyPrefab, config.position);
                            break;
                        case EnumMode.RelativePostion:
                            GenerateAtRelativePosition(config.enemyPrefab, config.position);
                            break;
                        case EnumMode.GlobalRight:
                        case EnumMode.GlobalLeft:
                            GenerateAtGlobal(config);
                            break;
                    }
                });
                if(genTimes>0){
                    genTimes--;
                }
            });
        }
    }

    public void StartWork()
    {
        if (!working)
        {
            working = true;
        }
    }
    public void StopWork()
    {
        if (working)
        {
            working = false;
        }
    }

    private void GenerateAtGlobal(Config config)
    {
        float viewportX = config.mode == EnumMode.GlobalRight ? 1f : 0f;

        Vector3 positionAtRightUp = mainCamera.ViewportToWorldPoint(new Vector3(viewportX, 1, 0));

        List<RaycastHit2D> hits = new List<RaycastHit2D>();
        Vector2 originPoint = positionAtRightUp;
        float distance = mainCamera.orthographicSize * 2;
        while (distance > 0)
        {
            RaycastHit2D hit = Physics2D.Raycast(originPoint, Vector2.down, mainCamera.orthographicSize * 2, config.groundLayer);
            if (hit)
            {
                hits.Add(hit);
                distance -= Vector2.Distance(originPoint, hit.point);
                originPoint = hit.point + Vector2.down * 1f;
            }
            else
            {
                distance = 0;
            }
        }

        Vector2 genPoint;
        if (hits.Count > 0)
        {
            genPoint = hits[Random.Range(0, hits.Count)].point;
            genPoint.y += 0.0625f;
            GenEnemyAtPoint(config.enemyPrefab, genPoint);
        }
        //else
        //{
        //    genPoint = mainCamera.ViewportToWorldPoint(new Vector3(viewportX, Random.Range(0.3f,1f), 0));
        //}

    }

    private void GenerateAtRelativePosition(GameObject enemyPrefab, Vector2 position)
    {
        GenEnemyAtPoint(enemyPrefab,transform.position + new Vector3(position.x, position.y, 0));
    }

    private void GenEnemyAtPoint(GameObject enemyPrefab, Vector2 point)
    {
        GameObject go = Instantiate(enemyPrefab, point, Quaternion.identity);
        go.SetActive(true);
        if(go.TryGetComponent(out EnemyBase enemy)){
            if (enemy is EnemyBaseMovable)
            {
                ((EnemyBaseMovable)enemy).SetFootPosition(point);
            }

            enemy.Run();
        }
    }
    public void OnTriggerEnter2D(Collider2D collision)
    {
        if (Utility.IsLayer(collision.gameObject, "Player"))
        {
            StartWork();
        }
    }


    public virtual void OnTriggerExit2D(Collider2D collision)
    {
        if (Utility.IsLayer(collision.gameObject, "Player"))
        {
            StopWork();
        }
    }

    public virtual void OnTriggerStay2D(Collider2D collision)
    {
    }

    public virtual void OnCollisionEnter2D(Collision2D collision)
    {
    }

    public virtual void OnCollisionExit2D(Collision2D collision)
    {
    }

    public virtual void OnCollisionStay2D(Collision2D collision)
    {
    }
}
